﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace InfFront.InfoSources.Base.Design
{
    public partial class InfoSourceOwnedListDesignerControl : UserControl
    {
        #region Private Variables
        IHandler handler = null;
        #endregion Private Variables

        public InfoSourceOwnedListDesignerControl()
        {
            InitializeComponent();
        }

        [DefaultValue("caption")]
        public string CaptionText
        {
            get { return lblCaption.Text; }
            set { lblCaption.Text = value; }
        }

        #region Public interface

        internal IHandler Handler
        {
            get { return handler; }
        }

        public void RebuildWith(IHandler newHandler)
        {
            handler = newHandler;

            lvItems.BeginUpdate();
            lvItems.Items.Clear();
            if (Handler != null)
            {
                foreach (var item in Handler.GetItemsToShow())
                {
                    var lvi = new ListViewItem();
                    ResetItem(lvi, item);
                    lvItems.Items.Add(lvi);
                }
                miMore.Visible = Handler.HasAdditionalActions();
            }
            lvItems.EndUpdate();

            lvItems_SelectedIndexChanged(this, EventArgs.Empty);
        }

        public bool ActOnObjectChanged(IInfoSourceOwnedObject obj)
        {
            if (Handler == null || Handler.ActOnObjectChanged(obj))
            {
                int pos = FindPositionFor(obj);
                if (pos != -1)
                {
                    ResetItem(lvItems.Items[pos], obj);
                    return true;
                }
            }
            return false;
        }

        public bool ActOnObjectRemoved(IInfoSourceOwnedObject obj)
        {
            if (Handler == null || Handler.ActOnObjectRemoved(obj))
            {
                int pos = FindPositionFor(obj);
                if (pos != -1)
                {
                    lvItems.Items.RemoveAt(pos);
                    return true;
                }
            }
            return false;
        }

        public bool ActOnObjectAdded(IInfoSourceOwnedObject obj)
        {
            if (Handler == null || Handler.ActOnObjectAdded(obj))
            {
                var lvi = new ListViewItem();
                ResetItem(lvi, obj);
                lvItems.Items.Add(lvi);
                return true;
            }
            return false;
        }

        /// <summary>
        /// User action handling interface
        /// </summary>
        public interface IHandler
        {
            IEnumerable<IInfoSourceOwnedObject> GetItemsToShow();

            IEnumerable<Type> GetTypesForCreation();

            bool HasAdditionalActions();

            IEnumerable<IAction> GetAdditionalActions();

            void ExecuteAction(IAction action);

            void CreateNewItem(Type type);

            void DestroyItem(IInfoSourceOwnedObject obj);

            bool ActOnObjectChanged(IInfoSourceOwnedObject obj);

            bool ActOnObjectRemoved(IInfoSourceOwnedObject obj);

            bool ActOnObjectAdded(IInfoSourceOwnedObject obj);

            void SelectComponent(object component);

            void MoveItemUp(IInfoSourceOwnedObject obj);

            void MoveItemDown(IInfoSourceOwnedObject obj);
        }

        public interface IAction
        {
            string Caption { get; }
        }

        #endregion Public interface

        #region Private members

        private void ResetItem(ListViewItem lvi, IInfoSourceOwnedObject item)
        {
            lvi.Tag = item;
            lvi.SubItems.Clear();
            lvi.Text = item.Site.Name;
            lvi.SubItems.Add(item.Title);
        }

        private int FindPositionFor(IInfoSourceOwnedObject item)
        {
            for (int i = 0; i < lvItems.Items.Count; ++i)
            {
                var tag = (IInfoSourceOwnedObject)lvItems.Items[i].Tag;
                if (tag == item)
                    return i;
            }
            return -1;
        }

        #endregion Private members

        private void lvItems_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvItems.SelectedIndices.Count == 0)
            {
                if (Handler != null)
                    Handler.SelectComponent(null);
                miRemove.Enabled = false;
                btnItemUp.Enabled = false;
                btnItemDown.Enabled = false;
            }
            else
            {
                int index = lvItems.SelectedIndices[0];
                var item = (IInfoSourceOwnedObject)lvItems.Items[index].Tag;
                Handler.SelectComponent(item);
                miRemove.Enabled = true;
                btnItemUp.Enabled = index > 0;
                btnItemDown.Enabled = index < (lvItems.Items.Count - 1);
            }
        }

        private void btnItemUp_Click(object sender, EventArgs e)
        {
            int index = lvItems.SelectedIndices[0];
            var item = (IInfoSourceOwnedObject)lvItems.Items[index].Tag;

            var lvItem = lvItems.Items[index];
            lvItems.Items.RemoveAt(index);
            lvItems.Items.Insert(index - 1, lvItem);

            Handler.MoveItemUp(item);
        }

        private void btnItemDown_Click(object sender, EventArgs e)
        {
            int index = lvItems.SelectedIndices[0];
            var item = (IInfoSourceOwnedObject)lvItems.Items[index].Tag;

            var lvItem = lvItems.Items[index];
            lvItems.Items.RemoveAt(index);
            lvItems.Items.Insert(index + 1, lvItem);

            Handler.MoveItemDown(item);
        }

        private void lvItems_Enter(object sender, EventArgs e)
        {
            if (lvItems.SelectedIndices.Count == 0)
            {
                Handler.SelectComponent(null);
            }
            else
            {
                int index = lvItems.SelectedIndices[0];
                var item = (IInfoSourceOwnedObject)lvItems.Items[index].Tag;
                Handler.SelectComponent(item);
            }
        }

        private void miAdd_DropDownOpening(object sender, EventArgs e)
        {
            miAdd.DropDownItems.Clear();
            foreach (var type in Handler.GetTypesForCreation())
            {
                var item = new ToolStripMenuItem();
                item.Text = type.FullName;
                item.Tag = type;
                item.Font = menu.Font;
                miAdd.DropDownItems.Add(item);
            }
        }

        private void miAdd_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            Handler.CreateNewItem((Type)e.ClickedItem.Tag);
        }

        private void miRemove_Click(object sender, EventArgs e)
        {
            foreach (int i in lvItems.SelectedIndices)
            {
                var lvi = lvItems.Items[i];
                Handler.DestroyItem((IInfoSourceOwnedObject)lvi.Tag);
            }
        }

        private void miMore_DropDownOpening(object sender, EventArgs e)
        {
            miMore.DropDownItems.Clear();
            foreach (var act in Handler.GetAdditionalActions())
            {
                var item = new ToolStripMenuItem();
                item.Text = act.Caption;
                item.Tag = act;
                item.Font = menu.Font;
                miMore.DropDownItems.Add(item);
            }
        }

        private void miMore_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            Handler.ExecuteAction((IAction)e.ClickedItem.Tag);
        }
    }
}
